package com.xlh.controller.course;

import cn.hutool.core.util.RandomUtil;
import com.google.common.collect.Lists;
import com.xlh.aop.CourseTesting;
import com.xlh.aop.OperationRecording;
import com.xlh.common.Result;
import com.xlh.common.ResultEnum;
import com.xlh.constant.UserConstant;
import com.xlh.dto.course.*;
import com.xlh.dto.system.OperationDTO;
import com.xlh.dto.system.ResourceRelationDTO;
import com.xlh.enums.LocalResourcesEnum;
import com.xlh.enums.ResourceRelationTypeEnum;
import com.xlh.enums.ResourcesTypeEnum;
import com.xlh.enums.course.AuthorityOperatingTypeEnum;
import com.xlh.enums.course.ChapterResourceViewEnum;
import com.xlh.enums.course.ChapterTypeEnum;
import com.xlh.enums.course.NotesTypeEnum;
import com.xlh.enums.user.EventCodeEnum;
import com.xlh.enums.user.RoleEnum;
import com.xlh.exception.common.BadRequestException;
import com.xlh.param.course.*;
import com.xlh.pojo.course.Chapter;
import com.xlh.security.UserInfoHolder;
import com.xlh.service.course.ChapterService;
import com.xlh.service.course.CourseService;
import com.xlh.service.course.TaskService;
import com.xlh.service.system.OperationService;
import com.xlh.service.system.SystemResourceService;
import com.xlh.util.BeanUtil;
import com.xlh.util.FileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 章节
 * <p>
 * Created by lx on 2019/1/25.
 */
@Api(tags = "ChapterController", description = "课程章节")
@RestController
@RequestMapping("/course/{courseId}/chapter")
public class ChapterController {

    private static Logger logger = LoggerFactory.getLogger(ChapterController.class);

    @Autowired
    private CourseService courseService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private SystemResourceService resourceService;

    @Autowired
    private OperationService operationService;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private TaskService taskService;

    @ApiOperation("获取某课程的章节列表")
    @GetMapping("/list")
    @PreAuthorize("@permissionValidator.isTeacherOrStudent()")
    public Result<List<ChapterBasicDTO>> listChapter(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId) {
        return Result.success(chapterService.listChapter(courseId));
    }

    @ApiOperation("获取当前用户的最近学习章节记录")
    @GetMapping("/operation")
    @PreAuthorize("@permissionValidator.isTeacherOrStudent()")
    public Result<OperationDTO> getChapterOperation(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId) {
        OperationDTO chapterRecording = operationService.getChapterRecording(userInfoHolder.getUserId(), courseId);
        if (chapterRecording != null) {
            List<ChapterBasicInfoDTO> infos = chapterService.listChapterInfo(
                    null, Lists.newArrayList(chapterRecording.getId()), ChapterTypeEnum.getManyExperiment());
            if (CollectionUtils.isNotEmpty(infos)
                    && infos.get(0).getParentId() != null && infos.get(0).getParentId() > 0) {
                infos = chapterService.listChapterInfo(
                        null, Lists.newArrayList(infos.get(0).getParentId()), null);
                if (CollectionUtils.isNotEmpty(infos)) {
                    chapterRecording.setId(infos.get(0).getId());
                    chapterRecording.setName(infos.get(0).getName());
                }
            }
        }
        return Result.success(chapterRecording);
    }

    @ApiOperation("获取某章节的资源笔记")
    @GetMapping("/{id}/resource/notes")
    @CourseTesting(key = "#{courseId}")
    @PreAuthorize("@permissionValidator.isTeacher() or (@permissionValidator.isStudent() and !@permissionValidator.isStudentEndClass(#courseId))")
    public Result<String> getNotesContent(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam @ApiParam(value = "笔记类型", required = true) Byte notesType,
            @RequestParam(required = false, defaultValue = "1") @ApiParam(value = "页数") Integer pageNumber) {
        return Result.success(chapterService.getNotesContent(courseId, chapterId,
                NotesTypeEnum.getByCode(notesType), pageNumber));
    }

    @ApiOperation("添加/修改某章节的资源笔记")
    @PostMapping("/{id}/resource/notes")
    @CourseTesting(key = "#{courseId}")
    @PreAuthorize("@permissionValidator.isTeacher() or (@permissionValidator.isStudent() and !@permissionValidator.isStudentEndClass(#courseId))")
    public Result updateNotesContent(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestBody @Valid NotesParam param) {
        chapterService.updateNotesContent(courseId, chapterId, param);
        return Result.success();
    }

    @ApiOperation("获取教师自己的章节列表")
    @GetMapping("/list/owner")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result<List<ChapterBasicInfoDTO>> listChapterOwner(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId) {
        return Result.success(chapterService.listChapter(Lists.newArrayList(courseId)));
    }

    @ApiOperation("添加章节")
    @PostMapping()
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result createChapter(@PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                @RequestBody @Valid ChapterParam param) {
        chapterService.createChapter(courseId, param);
        return Result.success();
    }

    @ApiOperation("修改某章节")
    @PutMapping("/{id}")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result updateChapter(@PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
                                @RequestBody @Valid ChapterParam param) {
        // 网络管理员删除：数据库真删，超管删除：数据库假删
        boolean logicDeleted = RoleEnum.INTERNET_ADMIN.getRoleCode() == userInfoHolder.getUser().getRole() ?
                false : true;

        chapterService.updateChapterInfo(courseId, chapterId, param, logicDeleted);
        return Result.success();
    }

    @ApiOperation("修改某章节显隐")
    @PutMapping("/{id}/falg")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result updateChapterFalg(@PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                    @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
                                    @RequestBody @Valid ClassCourseParam param) {

        chapterService.updateChapterFalg(courseId, chapterId, param.getFalg(), param.getType());
        return Result.success();
    }

    @ApiOperation("获取剪切板显隐")
    @GetMapping("/{id}/ClipboardFalg")
//    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result getClipboardFalg(@PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                   @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId
    ) {
        Integer clipboardFalg = chapterService.getClipboardFalg(courseId, chapterId);
        if (clipboardFalg == null) throw new BadRequestException("剪切板显示异常");
        return Result.success(clipboardFalg);
    }

    @ApiOperation("批量删除章节")
    @PostMapping("/batch-delete")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result deleteChapter(@PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                @RequestBody @ApiParam(value = "章节id集合", required = true) List<Long> chapterIds) {
        // 网络管理员删除：数据库真删，超管删除：数据库假删
        boolean logicDeleted = RoleEnum.INTERNET_ADMIN.getRoleCode() == userInfoHolder.getUser().getRole() ?
                false : true;
        chapterService.deleteChapter(Lists.newArrayList(courseId), chapterIds, logicDeleted,
                true, null);
        return Result.success();
    }

    @ApiOperation("导入存在的章节")
    @PostMapping("/import-exist")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result importExistChapter(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @RequestBody @ApiParam(value = "导入数据", required = true) List<Long> chapterIds) {
        chapterService.importExistChapter(null, courseId, chapterIds);
        return Result.success();
    }

    @ApiOperation("获取自己的章节ztree格式")
    @GetMapping("/ztree")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result<List<ZtreeDTO>> queryChapterOwner(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId) {
        return Result.success(chapterService.getChapterOwner(courseId));
    }

    @ApiOperation("调整章节顺序")
    @PostMapping("/order-adjustments")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result orderAdjustmentsChapter(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @RequestBody @ApiParam(value = "调整后章节id集合", required = true) List<Long> chapterIds) {
        chapterService.orderAdjustmentsChapter(courseId, chapterIds);
        return Result.success();
    }

    @ApiOperation("获取我的课程详情-某课程的资源信息")
    @GetMapping("/{id}/detail/resource")
    @PreAuthorize("@permissionValidator.isTeacherOrStudent()")
    @CourseTesting(key = "#{courseId}")
    @OperationRecording(codeEnum = EventCodeEnum.CHAPTER_RECORDING, objId = "#{chapterId}", type = "#{type}")
    public Result<Map<String, ResourceInfoDTO>> getChapterResourceInfo(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam(required = false) @ApiParam(value = "步骤与章节的id") Long stepChapterId,
            @RequestParam @ApiParam(value = "类型", required = true) Integer type) {
        ChapterResourceViewEnum viewEnum = ChapterResourceViewEnum.getByCode(type);
        if (viewEnum == null) {
            throw new BadRequestException();
        }
        return Result.success(chapterService.queryChapterResourceInfo(
                courseId, chapterId, stepChapterId, viewEnum.getResourcesTypeEnums()));
    }

    @ApiOperation("获取创作课程的某课程的资源信息")
    @GetMapping("/{id}/make/resource")
    @PreAuthorize("permitAll()")
    public Result<Map<String, ResourceInfoDTO>> queryChapterResourceInfo(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam(required = false) @ApiParam(value = "步骤与章节的id") Long stepChapterId,
            @RequestParam @ApiParam(value = "类型", required = true) List<Integer> types) {
        return Result.success(
                chapterService.queryChapterResourceInfo(courseId, chapterId,
                        stepChapterId, ResourcesTypeEnum.getByCodes(types)));
    }

    @ApiOperation("添加/修改某章节的资源信息")
    @PostMapping("/{id}/resource-online")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result createOrUpdateOnlineResource(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam @ApiParam(value = "资源类型", required = true) Integer resourceType,
            @RequestParam(required = false) @ApiParam(value = "步骤与章节的id") Long stepChapterId,
            @RequestBody @ApiParam(value = "修改资源信息", required = true) CreateResourceParam param) {
        chapterService.createOrUpdateResource(courseId, chapterId, stepChapterId,
                ResourcesTypeEnum.getByCode(resourceType), null, param);
        return Result.success();
    }

    @ApiOperation("添加/修改某章节的资源信息")
    @PostMapping("/{id}/resource-file")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result createOrUpdateFileResource(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam @ApiParam(value = "资源类型", required = true) Integer resourceType,
            @RequestParam(required = false) @ApiParam(value = "步骤与章节的id") Long stepChapterId,
            @RequestParam(value = "files") @ApiParam(value = "上传的文件的集合", required = true) MultipartFile[] files,
            @RequestParam @ApiParam(value = "资源名称", required = true) String name) {
        CreateResourceParam param = new CreateResourceParam();
        param.setName(name);
        chapterService.createOrUpdateResource(courseId, chapterId, stepChapterId,
                ResourcesTypeEnum.getByCode(resourceType), files, param);
        return Result.success();
    }

    @ApiOperation("删除某章节的资源信息")
    @PostMapping("/{id}/resource")
    @PreAuthorize("@permissionValidator.isAdmin() or @permissionValidator.isCourseOwner(#courseId)")
    public Result deleteFileResource(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam(required = false) @ApiParam(value = "步骤与章节的id") Long stepChapterId,
            @RequestParam @ApiParam(value = "资源类型", required = true) Integer resourceType,
            @RequestBody @ApiParam(value = "参数", required = true) CreateResourceParam param) {
        chapterService.deleteResource(courseId, chapterId, stepChapterId,
                ResourcesTypeEnum.getByCode(resourceType), param.getName());
        return Result.success();
    }

    @ApiOperation("读取文件")
    @GetMapping("/{id}/resource/read")
    @PreAuthorize("permitAll()")
    public void readResource(HttpServletResponse response,
                             @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                             @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
                             @RequestParam(required = false, defaultValue = "2") Integer type) {

        List<ResourceRelationDTO> resourceRelationDTOS = resourceService.getResourceRelationInfo(
                Lists.newArrayList(chapterId), Lists.newArrayList(type), null,
                ResourceRelationTypeEnum.CHAPTER.getCode());
        if (CollectionUtils.isNotEmpty(resourceRelationDTOS)) {
            ResourceRelationDTO resourceRelationDTO = resourceRelationDTOS.get(resourceRelationDTOS.size() - 1);
            String localUploadPath = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
                    new String[]{resourceRelationDTO.getRemark()}, resourceRelationDTO.getFileName());
            File file = new File(localUploadPath);
            if (file.exists()) {
                byte[] data = null;
                try (FileInputStream input = new FileInputStream(file)) {
                    data = new byte[input.available()];
                    input.read(data);
                    response.getOutputStream().write(data);
                } catch (Exception e) {
                    logger.error("读取文件异常", e);
                }

            } else {
                return;
            }
        }


    }

    @ApiOperation("下载zip文件")
    @GetMapping("/{id}/resource/zip")
    @PreAuthorize("permitAll()")
    public Result readResourceZip(HttpServletResponse response,
                                  @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
                                  @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
                                  @RequestParam(required = false, defaultValue = "2") Integer type,
                                  @RequestParam(required = false, defaultValue = "") String token) {

        List<ResourceRelationDTO> resourceRelationDTOS = resourceService.getResourceRelationInfo(
                Lists.newArrayList(chapterId), Lists.newArrayList(type), null,
                ResourceRelationTypeEnum.CHAPTER.getCode());
        File file = null;
        ResourceRelationDTO resourceDTO = null;
        ResourceRelationDTO resourceDTO1 = null;
        String localUploadPath = "";
        String localUploadPath1 = "";
        File[] srcFiles = null;
        try {
            if (CollectionUtils.isNotEmpty(resourceRelationDTOS)) {
                if (resourceRelationDTOS.size() > 1) {
                    resourceDTO = resourceRelationDTOS.get(1);
                    resourceDTO1 = resourceRelationDTOS.get(0);
                    localUploadPath = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
                            new String[]{resourceDTO.getRemark()}, resourceDTO.getFileName());
                    localUploadPath1 = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
                            new String[]{resourceDTO1.getRemark()}, resourceDTO1.getFileName());
                    srcFiles = new File[]{new File(localUploadPath), new File(localUploadPath1)};
                } else {
                    resourceDTO = resourceRelationDTOS.get(0);
                    localUploadPath = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
                            new String[]{resourceDTO.getRemark()}, resourceDTO.getFileName());
                    srcFiles = new File[]{new File(localUploadPath)};
                }

                File zipFile = new File(resourceDTO.getFileName() + ".zip");
                // 调用压缩方法
                file = FileUtil.zipFiles(srcFiles, zipFile);
//            FileParam param = chapterService.getTokenValueAndRemove(token);
//            String filePath = courseService.checkAndGetFilePath(ResourcesTypeEnum.PRESET_RESOURCE.getCode(), param);
//            String url = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
//                    new String[]{param.getRemark()}, param.getFileName());
                FileUtil.downloadFile(response, file.toString(), zipFile.toString());
            }
        } catch (Exception e) {
            return Result.error(ResultEnum.SERVER_ERROR);
        }
        return Result.success();

    }

    @ApiOperation("是否允许下载资源文件")
    @PostMapping("/{id}/resource/file-download/permission")
    public Result<String> fileDownloadPermission(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestBody @Valid FileParam param) {
        chapterService.checkResource(courseId, param);
        String uuid = RandomUtil.simpleUUID();
        UserConstant.DOWNLOAD_FILE_MAP.put(userInfoHolder.getUserId() + uuid, param);
        return Result.success(uuid);
    }

    @ApiOperation("下载资源文件")
    @GetMapping("/{id}/resource/file-download")
    public Result fileDownload(
            HttpServletResponse response,
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestParam @ApiParam(value = "token", required = true) String token) {

        FileParam param = chapterService.getTokenValueAndRemove(token);
        chapterService.checkResource(courseId, param);

        // 下载资源
        try {
            String file = LocalResourcesEnum.CHAPTER.getLocalUploadPath(
                    new String[]{param.getRemark()}, param.getFileName());
            FileUtil.downloadFile(response, file, param.getFileName());
        } catch (Exception e) {
            return Result.error(ResultEnum.SERVER_ERROR);
        }

        return Result.success();
    }

    @ApiOperation("获取某课程的所有章节权限")
    @PostMapping("/authority")
    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result<List<AuthorityDTO>> queryChapterAuthority(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @RequestParam @ApiParam(value = "类型 ChapterTypeEnum枚举", required = true) List<Integer> types,
            @RequestParam @ApiParam(value = "操作类型 1:对课程 2：对章节", required = true) Integer operatingType,
            @RequestBody @ApiParam(value = "查询的参数", required = true) @Valid List<ResourceAuthorityParam> params) {

        // 获取所有的章节 以及区分出 任务数据、章节数据
        List<ChapterBasicInfoDTO> tasks = chapterService.listTask(Lists.newArrayList(courseId), types, true);
        if (CollectionUtils.isEmpty(tasks)) {
            return Result.error(ResultEnum.NOT_FOUND, "暂无相应的章节");
        }

        List<AuthorityDTO> authorityDTOS = BeanUtil.batchTransform(AuthorityDTO.class, tasks);

        Map<ResourcesTypeEnum, List<String>> typeEnumListMap = params.stream()
                .collect(Collectors.toMap(o -> ResourcesTypeEnum.getByCode(o.getResourcesType()),
                        ResourceAuthorityParam::getNames));
        List<Long> chapterIds = authorityDTOS.stream()
                .map(AuthorityDTO::getId).collect(Collectors.toList());

        Long userId = courseService.getCourseById(courseId).getUserId();

        Map<Long, List<ResourceAuthorityDTO>> chapterAuthorityMap = chapterService.queryResourceAuthority(userId,
                typeEnumListMap, AuthorityOperatingTypeEnum.getByCode(operatingType), chapterIds);

        authorityDTOS.forEach(infoDTO -> {
            if (CollectionUtils.isNotEmpty(chapterAuthorityMap.get(infoDTO.getId()))) {
                List<ResourceAuthorityDTO> resourceAuthorityDTOS = chapterAuthorityMap.get(infoDTO.getId());
                infoDTO.setShowed(resourceAuthorityDTOS.get(0).getShowed());
                infoDTO.setDownloaded(resourceAuthorityDTOS.get(0).getDownloaded());
            }
        });

        return Result.success(authorityDTOS);
    }

    @ApiOperation("获取课程名和章节名称")
    @GetMapping("/{id}")
    @PreAuthorize("permitAll()")
    public Result<CourseChapterDTO> queryCourseChapterInfo(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId) {

        ChapterBasicInfoDTO chapterBasicInfoDTO = null;
        if (chapterId > 0) {
            List<ChapterBasicInfoDTO> data = chapterService.listChapter(Lists.newArrayList(courseId),
                    Lists.newArrayList(chapterId), null, null);
            if (CollectionUtils.isEmpty(data)) {
                return Result.error(ResultEnum.NOT_FOUND);
            }
            chapterBasicInfoDTO = data.get(0);
        }

        List<CourseDTO> courseDTOS = courseService.listCourse(null, null, null, null,
                Lists.newArrayList(courseId));
        if (CollectionUtils.isEmpty(courseDTOS)) {
            return Result.error(ResultEnum.NOT_FOUND);
        }

        return Result.success(new CourseChapterDTO(courseDTOS.get(0).getName(),
                chapterBasicInfoDTO == null ? "" : chapterBasicInfoDTO.getName()));
    }

    @ApiOperation("获取任务列表")
    @PostMapping("/{id}/task/list")
    @PreAuthorize("permitAll()")
    public Result<List<TaskDTO>> listTask(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestBody @ApiParam(value = "查询关键字") TaskInfoParam param) {
        return Result.success(taskService.listTask(courseId, chapterId, param));
    }

    @ApiOperation("任务排序")
    @PutMapping("/{id}/task/sort")
    @PreAuthorize("permitAll()")
    public Result updateTaskSort(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestBody @Valid List<Long> taskIds) {
        taskService.updateTaskSort(courseId, chapterId, taskIds);
        return Result.success();
    }

    @ApiOperation("添加任务基本信息")
    @PostMapping("/{id}/task")
    @PreAuthorize("permitAll()")
    public Result createTaskInfo(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @RequestBody @Valid CreateOrUpdateTaskParam param) {
        taskService.createTask(chapterId, param);
        return Result.success();
    }

    @ApiOperation("修改任务基本信息")
    @PutMapping("/task/{taskId}")
    @PreAuthorize("permitAll()")
    public Result updateTaskInfo(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("taskId") @ApiParam(value = "任务id", required = true) Long taskId,
            @RequestBody @Valid CreateOrUpdateTaskParam param) {
        taskService.updateTask(taskId, param);
        return Result.success();
    }

    @ApiOperation("删除任务")
    @DeleteMapping("/{id}/task/{taskId}")
    @PreAuthorize("permitAll()")
    public Result deleteTask(
            @PathVariable("courseId") @ApiParam(value = "课程id", required = true) Long courseId,
            @PathVariable("id") @ApiParam(value = "章节id", required = true) Long chapterId,
            @PathVariable("taskId") @ApiParam(value = "任务id", required = true) Long taskId) {
        // 网络管理员删除：数据库真删，超管删除：数据库假删
        boolean logicDeleted = RoleEnum.INTERNET_ADMIN.getRoleCode() == userInfoHolder.getUser().getRole() ?
                false : true;
        chapterService.deleteChapter(
                Lists.newArrayList(courseId), Lists.newArrayList(taskId), logicDeleted,
                true, null);
        return Result.success();
    }

    @ApiOperation("获取章节信息")
    @GetMapping("/{id}/info")
    @PreAuthorize("permitAll()")
    public Result<ChapterBasicInfoDTO> getChapterInfo(
            @PathVariable("courseId") Long courseId, @PathVariable("id") Long chapterId) {
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapterInfo(
                Lists.newArrayList(courseId), Lists.newArrayList(chapterId), null);
        if (CollectionUtils.isEmpty(chapters)) {
            return Result.error(ResultEnum.NOT_FOUND);
        }
        return Result.success(chapters.get(0));
    }

    @ApiOperation("修改章节/任务信息")
    @PostMapping("/{id}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateTaskInfo(
            @PathVariable("courseId") Long courseId, @PathVariable("id") Long chapterId,
            @RequestBody @Valid ChapterScoreParam param) {

        // 获取信息
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapterInfo(
                Lists.newArrayList(courseId), Lists.newArrayList(chapterId), null);
        if (CollectionUtils.isEmpty(chapters)) {
            return Result.error(ResultEnum.NOT_FOUND);
        }

        // 修改信息
        Chapter chapter = new Chapter();
        chapter.setId(chapterId);
        chapter.setDifficultyScore(param.getScore());
        chapterService.updateChapterSelective(chapter);
        return Result.success();
    }

}
